home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / rpg / crossfir.92 / crossfir / crossfire-0.92.5 / server / encounter.c < prev    next >
C/C++ Source or Header  |  1996-07-24  |  7KB  |  271 lines

  1. /*
  2.  * static char *rcsid_encounter_c
  3.  *   "$Id: encounter.c,v 1.8 1994/11/09 03:39:31 master Exp $";
  4.  */
  5. /*
  6.     CrossFire, A Multiplayer game for X-windows
  7.  
  8.     Copyright (C) 1992 Frank Tore Johansen
  9.  
  10.     This program is free software; you can redistribute it and/or modify
  11.     it under the terms of the GNU General Public License as published by
  12.     the Free Software Foundation; either version 2 of the License, or
  13.     (at your option) any later version.
  14.  
  15.     This program is distributed in the hope that it will be useful,
  16.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.     GNU General Public License for more details.
  19.  
  20.     You should have received a copy of the GNU General Public License
  21.     along with this program; if not, write to the Free Software
  22.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23.  
  24.     The author can be reached via e-mail to frankj@ifi.uio.no.
  25. */
  26.  
  27. #include <global.h>
  28. #include <ctype.h>
  29. #ifndef __CEXTRACT__
  30. #include <sproto.h>
  31. #endif
  32.  
  33. #ifdef RANDOM_ENCOUNTERS
  34.  
  35. struct encounter_alt {
  36.   int num;
  37.   char *path;
  38.   struct encounter_alt *next;
  39. };
  40.  
  41. static struct encounter_alt *encounter_alternatives = NULL;
  42.  
  43. /*
  44.  * Read the directory to find the number of available terrain maps,
  45.  * remember values in encounter_alternatives.
  46.  * 
  47.  * Beware! "path" is assumed to be a shared string!
  48.  */
  49. int find_encounter_alternatives(const char *lib, char *path) {
  50.   struct encounter_alt *enc = encounter_alternatives;
  51.  
  52.   while (enc) {
  53.     if (enc->path == path) {
  54.       return enc->num;
  55.     }
  56.     enc = enc->next;
  57.   }
  58.  
  59.   {
  60.     XDIR *dirp;
  61.     struct xdirect *direntry;
  62.     char buf[MAX_BUF], *basename;
  63.     int baselen;
  64.  
  65.     enc = malloc(sizeof(struct encounter_alt));
  66.     /* add_refcount() is declared wrongly, but fixing it is a lot
  67.      * work. Therefore we must live with a warning on the next line.
  68.      */
  69.     enc->path = add_refcount(path);
  70.     enc->next = encounter_alternatives;
  71.     enc->num = 0;
  72.  
  73.     sprintf(buf, "%s/%s", lib, path);
  74.  
  75.     basename = strrchr(buf, '/');
  76.     *basename++ = 0;
  77.     baselen = strlen(basename);
  78.   
  79.     dirp = xopendir(buf);
  80.     if (dirp == NULL) {
  81.       LOG(llevError, "Can't open terrain map directory (%s)\n", buf);
  82.       free(enc);
  83.       return 0;
  84.     }
  85.     while ((direntry = xreaddir(dirp, 0))!=NULL) {
  86.       /* The length of the filename under consideration should be at least
  87.        * two characters longer than basename, namely "_1"
  88.        */
  89.       if (baselen + 2 <= direntry->d_namlen
  90.          && !strncmp(basename, direntry->d_name, baselen)
  91.          && direntry->d_name[baselen] == '_'
  92.          && isdigit(direntry->d_name[baselen+1])) {
  93.        enc->num += 1;
  94.       }
  95.     }
  96.     xclosedir(dirp);
  97.     encounter_alternatives = enc;
  98.  
  99.     return enc->num;
  100.   }
  101. }
  102.   
  103. static int encounter_count = 0;
  104.  
  105. void random_encounter(object *pl, object *rnd_ob) {
  106.   char buf[MAX_BUF], buf2[MAX_BUF];
  107.   mapstruct *m, *m2;
  108.   object *exit_ob, *tmp, *op, *next;
  109.   object *mapobs[3][3];
  110.   int x,y,i;
  111.  
  112.   if (pl->type != PLAYER)
  113.     return;
  114.  
  115.   if (pl->map->encounter)
  116.     return; /* No encounters within encounters */
  117.   if (rnd_ob->head != NULL)
  118.     rnd_ob = rnd_ob->head;
  119.  
  120.   if (rnd_ob->slaying) {
  121.     enter_exit(pl, rnd_ob);
  122.     return;
  123.   }
  124.   if (RANDOM()%4)
  125.     return;
  126.  
  127.   /*
  128.    * Check if its possible to create an encounter map here.
  129.    */
  130.   for (x = (-1); x < 2; x++)
  131.     for (y = (-1); y < 2; y++)
  132.       if (out_of_map(pl->map, rnd_ob->x + x, rnd_ob->y + y) ||
  133.           (mapobs[x+1][y+1] = get_map_ob(pl->map, x + rnd_ob->x, y + rnd_ob->y))
  134.            == (object *) NULL ||
  135.           mapobs[x+1][y+1]->type != ENCOUNTER ||
  136.           mapobs[x+1][y+1]->slaying != (char *) NULL ||
  137.           mapobs[x+1][y+1]->race == (char *) NULL ||
  138.           (mapobs[x+1][y+1]->above != NULL &&
  139.        !QUERY_FLAG(mapobs[x+1][y+1]->above, FLAG_ALIVE)) ||
  140.           (mapobs[x+1][y+1]->below != NULL &&
  141.        !QUERY_FLAG(mapobs[x+1][y+1]->below,FLAG_ALIVE))) return;
  142.  
  143.   sprintf(buf, "/encounter#%d", encounter_count++);
  144.   m = ready_map_name("/terrain/empty", 0);
  145.   m->encounter = 1;
  146.   strcpy(m->path, buf);
  147. #if 0
  148.   if (m->map_object->name)
  149.     free_string(m->map_object->name);
  150.   m->map_object->name = add_string(buf);
  151. #endif
  152.   rnd_ob->slaying = add_refcount(m->map_object->name);
  153.  
  154.   /*
  155.    * Read the terrains from the different squares of the map
  156.    * which we are generating.  Then relink their objects onto
  157.    * the new map.
  158.    * Also, in the same loop, make the eight surrounding
  159.    * terrain objects into exits which leads to the correct
  160.    * spot on the map.
  161.    */
  162.   for (x = 0; x < 3; x++)
  163.     for (y= 0; y < 3; y++)
  164.     {
  165.       int r;
  166.  
  167.       mapobs[x][y]->stats.hp = x*11 + 6;
  168.       mapobs[x][y]->stats.sp = y*11 + 6;
  169.       mapobs[x][y]->slaying = add_string(buf);
  170.       sprintf(buf2, "%s/%s", LibDir, MapDir);
  171.       r = find_encounter_alternatives(buf2, mapobs[x][y]->race);
  172.       sprintf(buf2, "%s_%ld", mapobs[x][y]->race, (long)RANDOM()%r+1);
  173.       m2 = load_original_map(buf2, 1); /* 1 so that the game blocks */
  174.       if (m2 == (mapstruct *) NULL)
  175.       {
  176.         LOG(llevError, "Failed to read map %s\n", buf2);
  177.     CLEAR_FLAG(rnd_ob, FLAG_WALK_ON);
  178.         rnd_ob->type = 0;
  179.         return;
  180.       }
  181.       relink_objs_offset(m2, m, x * 11, y * 11);
  182.       free_map(m2, 1);
  183.       delete_map(m2);
  184.     }
  185.  
  186.   exit_ob = get_archetype("invis_exit");
  187.   if (exit_ob == (object *) NULL)
  188.   {
  189.     LOG(llevError, "Couldn't find archetype invis_exit.\n");
  190.     free_object(exit_ob);
  191.     return;
  192.   }
  193.  /* We want dimension door to stop before it */
  194.   SET_FLAG(exit_ob, FLAG_NO_MAGIC);
  195.   exit_ob->slaying = add_string(rnd_ob->map->path);
  196.  
  197.   /*
  198.    * Put exits around the edge of the map, and make them point
  199.    * to the correct square outside.
  200.    */
  201.   for (x = 0; x < 3; x++)
  202.     for (y = 0; y < 3; y++)
  203.     {
  204.       exit_ob->stats.hp = rnd_ob->x + x - 1;
  205.       exit_ob->stats.sp = rnd_ob->y + y - 1;
  206.       for (i = 0; i < 11; i++)
  207.       {
  208.         if (x != 1) {
  209.           tmp = get_object();
  210.           copy_object(exit_ob, tmp);
  211.           if (x == 0)
  212.             tmp->x = 2, tmp->y = i + y*11;
  213.           else
  214.             tmp->x = 31, tmp->y = i + y*11;
  215.           insert_ob_in_map(tmp, m);
  216.         }
  217.         if (y != 1) {
  218.           tmp = get_object();
  219.           copy_object(exit_ob, tmp);
  220.           if (y == 0)
  221.             tmp->y = 2, tmp->x = i + x*11;
  222.           else
  223.             tmp->y = 31, tmp->x = i + x*11;
  224.           insert_ob_in_map(tmp, m);
  225.         }
  226.       }
  227.     }
  228.  
  229.   /*
  230.    * To avoid some bugs, make the edges impassable.
  231.    */
  232.   for (i = 0; i < 33; i++)
  233.   {
  234.     if ((op = get_map_ob(m, i,  0)) != (object *) NULL)
  235.       SET_FLAG(op, FLAG_NO_PASS);
  236.     if ((op = get_map_ob(m, i, 32)) != (object *) NULL)
  237.       SET_FLAG(op, FLAG_NO_PASS);
  238.     if ((op = get_map_ob(m,  0, i)) != (object *) NULL)
  239.       SET_FLAG(op, FLAG_NO_PASS);
  240.     if ((op = get_map_ob(m, 32, i)) != (object *) NULL)
  241.       SET_FLAG(op, FLAG_NO_PASS);
  242.   }
  243.  
  244.   /*
  245.    * Clear the centre of the map for monsters.
  246.    */
  247.   for (x = 11; x < 22; x++)
  248.     for (y = 11; y < 22; y++)
  249.       for (op = get_map_ob(m, x, y); op; op = next)
  250.       {
  251.         next = op->above;
  252.         if (QUERY_FLAG(op,FLAG_MONSTER)) {
  253.           remove_ob(op);
  254.           free_object(op);
  255.         }
  256.       }
  257.  
  258.   free_object(exit_ob);
  259.  
  260.   /*
  261.    * Now generate the treasure within the monsters
  262.    */
  263.   fix_auto_apply(m);
  264.  
  265.   /*
  266.    * Go for it!
  267.    */
  268.   enter_exit(pl, rnd_ob);
  269. }
  270. #endif
  271.